package com.lambkit.core;

import com.lambkit.core.config.AppConfig;
import com.lambkit.core.flow.FlowWorkCenter;
import com.lambkit.core.pipeline.DefaultPipeLineFactory;
import com.lambkit.core.pipeline.IPipeLineFactory;
import com.lambkit.core.pipeline.PipeLineService;
import com.lambkit.core.plugin.IPlugin;
import com.lambkit.core.plugin.Plugins;
import com.lambkit.core.service.*;
import com.lambkit.core.service.impl.DefaultBeanFactory;
import com.lambkit.core.service.impl.DefaultClassOperateFactory;
import com.lambkit.core.service.impl.DefaultResourceFactory;
import com.lambkit.core.task.IWorkCenter;
import com.lambkit.util.Printer;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * Lambkit的上下文
 * @author yangyong(孤竹行)
 */
public class AppContext extends BaseContext {
    private String name; // 应用名称
    private List<AppLifecycle> configList = new ArrayList<AppLifecycle>();
    /**
     * 模块类集合
     */
    private List<AppLifecycle> lifecycleList = new ArrayList<AppLifecycle>();

    private Plugins plugins = new Plugins();

    private FlowWorkCenter flowWorkCenter;

    private Map<Class<? extends IWorkCenter>, IWorkCenter> workCenters = new ConcurrentHashMap<>();

    private BeanContainer beanContainer = new BeanContainer();

    private IPipeLineFactory pipeLineFactory = new DefaultPipeLineFactory();

    private BeanFactory beanFactory = new DefaultBeanFactory();

    /**
     * 资源放置的方式，classpath会打包到jar中，webapp是指定路径的文件夹
     */
    private String resourcePathType = "classpath";
    /**
     * 静态资源文件夹名称
     */
    private String resourcePath = "static";
    /**
     * 模板资源文件夹名称
     */
    private String templatePath = "templates";

    private ResourceFactory resourceFactory = new DefaultResourceFactory();

    private ClassOperateFactory classOperateFactory = new DefaultClassOperateFactory();

    ///////////////////////////////////////////////////////////////

    public AppContext(String name) {
        this.name = name;
    }

    ///////////////////////////////////////////////////////////////
    public void addLifecycle(AppLifecycle lifecycle) {
        lifecycleList.add(lifecycle);
    }
    public void addAppConfigs(List<AppConfig> configs) {
        for (int i=0; i<configs.size(); i++) {
            AppConfig appConfig = configs.get(i);
            addAppConfig(appConfig);
        }
    }
    public void addAppConfig(AppConfig config) {
        if(!configList.contains(config)) {
            configList.add(config);
        }
    }

    public void addPlugins(List<IPlugin> plugins) {
        for (int i=0; i<plugins.size(); i++) {
            IPlugin plugin = plugins.get(i);
            addPlugin(plugin);
        }
    }
    public void addPlugin(IPlugin plugin) {
        plugins.add(plugin);
        Printer.print(this, "starter", "LambkitApp [{}] add Plugin: {}", Lambkit.app(name).getClass().getName(), plugin.getClass().getName());
    }

    public <T extends IWorkCenter> void addWorkCenter(T workCenter)  {
        this.workCenters.put(workCenter.getClass(), workCenter);
    }

    public <T extends IWorkCenter> T getWorkCenter(Class<T> workCenterClass)  {
        IWorkCenter workCenter = this.workCenters.get(workCenterClass);
        if (false == workCenterClass.isInstance(workCenter)) {
            return null;
        }
        return (T) workCenter;
    }

    public <T> T getBean(Class<T> clazz) {
        T obj = beanContainer.getBean(clazz);
        if(obj == null && getBeanFactory() != null) {
            obj = getBeanFactory().get(clazz);
        }
        return obj;
    }
    ///////////////////////////////////////////////////////////////

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Map<Class<? extends IWorkCenter>, IWorkCenter> getWorkCenters() {
        return workCenters;
    }

    public void setWorkCenters(Map<Class<? extends IWorkCenter>, IWorkCenter> workCenters) {
        this.workCenters = workCenters;
    }

    public FlowWorkCenter getFlowWorkCenter() {
        return flowWorkCenter;
    }

    public void setFlowWorkCenter(FlowWorkCenter flowWorkCenter) {
        this.flowWorkCenter = flowWorkCenter;
    }

    public ClassOperateService classOperateService() {
        return getClassOperateFactory().getClassOperateService();
    }

    public ResourceService resourceService() {
        return getResourceFactory().getResourceService();
    }

    public PipeLineService pipeLineService() {
        return getPipeLineFactory().getPipeLineService();
    }

    public BeanFactory getBeanFactory() {
        return beanFactory;
    }

    public void setBeanFactory(BeanFactory beanFactory) {
        this.beanFactory = beanFactory;
    }

    public ClassOperateFactory getClassOperateFactory() {
        return classOperateFactory;
    }

    public void setClassOperateFactory(ClassOperateFactory classOperateFactory) {
        this.classOperateFactory = classOperateFactory;
    }

    public IPipeLineFactory getPipeLineFactory() {
        return pipeLineFactory;
    }

    public void setPipeLineFactory(IPipeLineFactory pipeLineFactory) {
        this.pipeLineFactory = pipeLineFactory;
    }

    public ResourceFactory getResourceFactory() {
        return resourceFactory;
    }

    public void setResourceFactory(ResourceFactory resourceFactory) {
        this.resourceFactory = resourceFactory;
    }

    public String getResourcePathType() {
        return resourcePathType;
    }

    public void setResourcePathType(String resourcePathType) {
        this.resourcePathType = resourcePathType;
    }

    public String getResourcePath() {
        return resourcePath;
    }

    public void setResourcePath(String resourcePath) {
        this.resourcePath = resourcePath;
    }

    public String getTemplatePath() {
        return templatePath;
    }

    public void setTemplatePath(String templatePath) {
        this.templatePath = templatePath;
    }

    public List<AppLifecycle> getLifecycleList() {
        return lifecycleList;
    }

    public void setLifecycleList(List<AppLifecycle> lifecycleList) {
        this.lifecycleList = lifecycleList;
    }

    public List<AppLifecycle> getConfigList() {
        return configList;
    }

    public void setConfigList(List<AppLifecycle> configList) {
        this.configList = configList;
    }

    public Plugins getPlugins() {
        return plugins;
    }

    public void setPlugins(Plugins plugins) {
        this.plugins = plugins;
    }
}
